<script>
import { deepClone } from '@/utils/index'
import render from '@/components/render/render.js'
import {getAccessToken} from "@/utils/auth";
import {getFormRule} from '@/api/custom/formDesigner'
const ruleTrigger = {
  'el-input': 'blur',
  'el-input-number': 'blur',
  'my-select': 'change',
  'my-radio-group': 'blur',
  'my-checkbox-group': 'blur',
  'el-cascader': 'change',
  'my-cascader': 'blur',
  'my-region': 'blur',
  'el-time-picker': 'change',
  'el-date-picker': 'change',
  'el-rate': 'change',
  'getMapPoint': 'blur',
  'PostSelection': 'blur',
  'UsersSelector': 'blur',
  'DepartmentSelection': 'blur',
  'Steps': 'blur',
}

const layouts = {
  colFormItem(h, scheme) {
    const config = scheme.__config__
    const listeners = buildListeners.call(this, scheme)
    let child = renderChildren.apply(this, arguments)
    let labelWidth = config.labelWidth ? `${config.labelWidth}px` : null
    if (config.showLabel === false) labelWidth = '0'
    // 预览时渲染
    if(config.tag==='Steps') {
      scheme.clickAble=false
      const down=()=>{
        this.$refs[this.formConf.formRef].validate(valid => {
        if (!valid) return false
        if(this.$store.state.currentStep.steps[scheme.activeId]<child.length-1) {
          this.$store.commit('DOWN', {key:scheme.activeId,value:this.$store.state.currentStep.steps[scheme.activeId]+1})
        }
        return true
        })
      }
      const up=()=>{
        if(this.$store.state.currentStep.steps[scheme.activeId]>0){
          this.$store.commit('UP', {key:scheme.activeId,value:this.$store.state.currentStep.steps[scheme.activeId]-1})
        }
      }
      const close=()=>{
        // this.$refs[this.formConf.formRef].validate(valid => {
        // if (!valid) return false
        // this.$emit('submit', this[this.formConf.formModel])
        // return true
        // })
      }
      const finish=()=>{
        this.submitForm()
      }
      return (
        <el-col span={config.span}>
           <el-row>
              <el-col span={this.$store.state.currentStep.steps[scheme.activeId]!==0?16:19} >
                <render conf={scheme} on={listeners}/>
              </el-col>
              <el-col span={this.$store.state.currentStep.steps[scheme.activeId]!==0?8:5}>
                <el-row>
                  <el-button onClick={up} v-show={this.$store.state.currentStep.steps[scheme.activeId]!==0}>{config.up}</el-button>
                  <el-button onClick={down} v-show={this.$store.state.currentStep.steps[scheme.activeId]!==child.length-1}>{config.down}</el-button>
                  <el-button  v-show={this.$store.state.currentStep.steps[scheme.activeId]===child.length-1} onClick={finish} type="primary">完成</el-button>
                  <el-button onClick={close} type="danger">{config.finish}</el-button>
                </el-row>
              </el-col>
            </el-row>
            {child[this.$store.state.currentStep.steps[scheme.activeId]]??0}
        </el-col>
      )
    }
    if(scheme.hide===true){
      return null
    }
    if(this.formConfCopy.disabled || this.status==='view'){
      //禁用富文本
      if(config.tag==='tinymce'){
        scheme.readonly = true
      }
    }
    let isShowDesc = ['Subform','TitleLine','el-tabs','Steps','el-collapse'].includes(config.tag);
    if(config.bianma){
      scheme.disabled = true;
    }
    return (
      <el-col span={config.span}>
        <el-form-item label-width={labelWidth} prop={scheme.__vModel__}
          label={config.showLabel ? config.label : ''}>
          {this.formConf.labelDescriptionPosition==='icon' && !isShowDesc &&  <span slot="label">{config.showLabel ? config.label : ''}
                    <el-tooltip content={config.descriptionMessage} placement="top">
                    <i class="el-icon-question" style={{color:'#cacad3'}}></i>
                    </el-tooltip>
                  </span>}
            <render conf={scheme} on={listeners}/>
          <div style={{color:'#909399'}}>{this.formConf.labelDescriptionPosition==='button' && !isShowDesc && config.descriptionMessage}</div>
        </el-form-item>
      </el-col>
    )
  },
  rowFormItem(h, scheme) {
    let child = renderChildren.apply(this, arguments)
    if (scheme.type === 'flex') {
      child = <el-row type={scheme.type} justify={scheme.justify} align={scheme.align}>
              {child}
            </el-row>
    }
    const config = scheme.__config__

    // 选项卡/折叠面板
    if (config.tag === 'el-tabs'||config.tag === 'el-collapse') {
      return (
        <el-col span={config.span}>
          <el-row gutter={config.gutter}>
            <render child={child} key={config.renderKey} conf={scheme}/>
          </el-row>
        </el-col>
      )
    }
    if(config.tag==='Subform'){
       const sortField = scheme.__config__.sortField;
       let children = this.testList(config.renderKey);
       const optionBtnNum = scheme.options.filter(item=>item.position!=='table').length
       const tableData = scheme.tableData.slice((config.curPage - 1) * Number(config.pageSize), config.curPage * Number(config.pageSize));
       const style='display:flex;height: 40px;line-height: 40px;justify-content: space-between;margin: 5px 0px;';
       return (
        <div>
        <el-col style='box-shadow:1px 1px 3px #d0d0d0,-5px -5px 10px #f0f0f0;border-radius: 10px;padding:0px 10px 10px 10px;margin: 10px 0px'>
            {// 表格按钮区 添加/删除/复制/上移/下移/导入/导出/编辑
            <div style={style}>
                <div style='font-weight: 600'>{config.label}</div>
                <div>
                {
                scheme.options
                .filter(item=>item.position==='table')
                .map(item=>
                <el-button
                    type={item.type}
                    size="mini"
                    onClick={()=>{
                        this.$emit(item.command, this.mulArr, config.renderKey)
                    }}>{item.label}
                </el-button>)
                }
                </div>
            </div>
            }
            <el-table
                data={tableData}
                border={config.formBorder}
                stripe
                highlight-current-row
                onSelect={this.handleSelectionChange}
                on-select-all={this.handleSelectionChange}>
                {// 多选
                <el-table-column
                type="selection"
                width="55"
                align="center"
                fixed>
                </el-table-column>
                }
            {config.showNum && !this.hideData[0]?.hide &&
                <el-table-column
                    {...{scopedSlots: {
                        // 序号，render函数内使用scope写法
                        default: (scope) => {
                            return scope.$index+1
                        }
                    }}}
                    width={config.numWidth}
                    label={config.numLabel}
                    align="center">
                </el-table-column>
            }
            { // 表格列以及数据渲染
            children.map((item,index)=> {
                const indexHide = config.showNum ? index + 1 : index
                const dom = <el-table-column
                    width={config.labelIsShow && config.columnWidth}
                    key={index}
                    column-key={index + ''}
                    // 左侧固定列与右侧固定列
                    fixed={(index < config.leftCol && 'left') || (config.rightCol + index + 1 > children.length && 'right')}
                    {...{scopedSlots: {
                        // render函数内使用scope写法
                        default: (scope) => {
                        item.__config__.defaultValue = scope.row[item.__vModel__]
                        const newItem={
                            ...item,
                            __config__:{
                                ...item.__config__,
                                defaultValue:scope.row[item.__vModel__]
                            }
                        }
                        const dom = <el-form-item prop={item.__vModel__} style='margin-top:20px' labelWidth="0">
                                        <render key={newItem.__config__.renderKey} conf={newItem} onInput={ event => {
                                        // 更改配置数据
                                        this.$set(item.__config__, 'defaultValue', event)
                                        // 更改配置数据tableData数据，不然数据丢失
                                        this.$listeners.updateTableData({ index:scope?.$index, field:item.__vModel__, value:event, renderKey: config.renderKey })
                                    }}/>
                                    </el-form-item>
                        return config.componentBorder ? dom : scope.row.showComp ? dom : <div>{item.__config__.defaultValue}</div>
                    }
                }}} label={item.__config__.label} align="center" min-width='200' sortable={sortField===item.__vModel__ ? true : false}>
                </el-table-column>
                return config.renderKey === this.hideData[indexHide]?.renderKey ? (!this.hideData[indexHide]?.hide && dom) : dom
                })
            }
            { // 表格操作列
            optionBtnNum > 0 ?
            <el-table-column width={optionBtnNum === 1 ? '80px' : optionBtnNum * 60 + 'px'}
            {...{scopedSlots: {
                default: (scope) => {
                    const btn=scheme.options.filter(item=>item.position!=='table')
                    return  btn.map((item, index)=> {
                        return <el-tooltip effect="light" content={item.label} placement="top">
                            <el-button type={item.type} onClick={()=>{
                                this.$emit(item.command, scope, config.renderKey, config.editType)
                            }}  key={index} size="mini" icon={item.iconType}>
                            </el-button>
                        </el-tooltip>
                    })
                }
            }}}  align="center" fixed="right"
            render-header={(h,{column,$index})=>{
                return config.showCustomColumn ? h('div',[h('span','操作'), h('i',{
                    class:'el-icon-s-operation',
                    style:'margin-left:5px;cursor:pointer',
                    on: {
                        click: () => this.explicit(config.renderKey), // 显隐
                    },
                })
                ]) : h('div',[h('span','操作')])
            }}>
            </el-table-column> : null
            }
            </el-table>
        </el-col>
        {config.isPage &&
        <el-pagination
            background
            layout="prev, pager, next, jumper"
            total={scheme.tableData.length}
            page-size={Number(config.pageSize)}
            current-page={config.curPage}
            style="float: right;margin-bottom:10px"
            on-current-change = {(curPage) => this.$emit('curPageChange', curPage, config.renderKey)}
            >
        </el-pagination>}
        </div>
      )
    }
    return (
      <el-col span={scheme.span}>
        <el-row gutter={scheme.gutter}>
          {child}
        </el-row>
      </el-col>
    )
  }
}

function renderFrom(h) {
  const { formConfCopy,status } = this
  return (
    <el-row gutter={formConfCopy.gutter}>
      <el-form
        size={formConfCopy.size}
        label-position={formConfCopy.labelPosition}
        disabled={formConfCopy.disabled||status==='view'}
        label-width={`${formConfCopy.labelWidth}px`}
        ref={formConfCopy.formRef}
        props={{ model: this[formConfCopy.formModel] }}
        rules={this[formConfCopy.formRules]}
      >
        {renderFormItem.call(this, h, this.formConfJson.fields)}
        {status!=='view' && formConfCopy.formBtns && formBtns.call(this, h)}
      </el-form>
    </el-row>
  )
}

function formBtns(h) {
  // return <el-col>
  //   <el-form-item size="large" style="textAlign:center;marginRight:100px;">
  //     <el-button type="primary" onClick={this.submitForm} size="small">提交</el-button>
  //     <el-button onClick={this.resetForm} size="small">重置</el-button>
  //   </el-form-item>
  // </el-col>

  // return <el-col>
  //   <el-form-item size="large" style="textAlign:center;marginRight:100px;">
  //     <el-button type="primary" onClick={this.submitForm} size="small">提交</el-button>
  //   </el-form-item>
  // </el-col>

  //按钮自定义配置
  const { formConfCopy } = this
  return <el-col>
    <div style={{'text-align':formConfCopy.btnPosition,paddingTop:'20px'}}>
      {formConfCopy.btnConfig.filter(item=>item.label!=='保存').map((item)=>{
        if (item.checked) {
          return <el-button type={item.type} onclick={this[`${item.click}Form`]} size="small">{item.text}</el-button>
        } else {
          return null
        }
      })}
    </div>
  </el-col>
}

function renderFormItem(h, elementList) {
  return elementList.map(scheme => {
    const config = scheme.__config__
    const layout = layouts[config.layout]
    if (layout) {
      return layout.call(this, h, scheme)
    }
    throw new Error(`没有与${config.layout}匹配的layout`)
  })
}

function renderChildren(h, scheme) {
  const config = scheme.__config__
  if (!Array.isArray(config.children)) return null
  return renderFormItem.call(this, h, config.children)
}

function setValue(event, config, scheme) {
  this.$set(config, 'defaultValue', event)
  this.$set(this[this.formConf.formModel], scheme.__vModel__, event)
}

//change事件，查询表单规则结果
function setShowHide() {
  if(this.formConfCopy.ruleConfig&&this.formConfCopy.ruleConfig.length>0){
    // this.ruleConfig.forEach((cur,index)=>{
      this.ruleConfig.formList = []
      Object.keys(this[this.formConf.formModel]).forEach(key => {
        this[this.formConf.formModel][key]!==null && this[this.formConf.formModel][key]!==undefined && this.ruleConfig.formList.push({
          filedName: key,
          value: Array.isArray(this[this.formConf.formModel][key])?this[this.formConf.formModel][key].join(','):this[this.formConf.formModel][key]
        })
      })
    // })
    getFormRule(this.ruleConfig).then((res)=>{
      if(res.code===0){
        if(res.data!==null && res.data !== '不符合规则'){
          this.hiddenFields = res.data.hiddenField.split(',')
          this.changeShowHide(this.formConfCopy.fields,this.hiddenFields)
        } else{
          this.hiddenFields = []
          this.changeShowHide(this.formConfCopy.fields,this.hiddenFields)
        }
      }
    }).catch(e=>console.log(e))
  }
}

function buildListeners(scheme) {
  const config = scheme.__config__
  const methods = this.formConf.__methods__ || {}
  const listeners = {}

  // 给__methods__中的方法绑定this和event
  Object.keys(methods).forEach(key => {
    listeners[key] = event => methods[key].call(this, event)
  })
  // 响应 render.js 中的 vModel $emit('input', val)
  listeners.input = event => setValue.call(this, event, config, scheme)
  // 响应 render.js 中的 vModel $emit('change', val)
  listeners.change = event => {
  //  console.log(event,'888888888')
    setShowHide.call(this)
  }
  return listeners
}

export default {
  components: {
    render
  },
  props: {
    formConf: {
      type: Object,
      required: true
    },
    status: {
      type: String,
      required: true
    },
    tableName: {
      type: String,
      default:'',
      required: false
    },
    originData: {
      type: Object,
      required: true
    },
    showHideData:{
       type: Array ,
      // required: true
    }
  },
  computed: {
    formConfJson () {
      return JSON.parse(JSON.stringify(this.formConf))
    },
    hideData(){
      return this.showHideData?JSON.parse(JSON.stringify(this.showHideData)):[]
    },
  },
  data() {
    this.bindUploadSuccess(this.formConf.fields, this.formConf.formModel)
    const data = {
        formConfCopy: deepClone(this.formConf),
        [this.formConf.formModel]: {},
        [this.formConf.formRules]: {},
        mulArr: [],
        ruleConfig: {}, //表单规则配置
        hiddenFields: [], //表单规则--隐藏字段
        redioValue: ''
    }
    this.initFormData(data.formConfCopy.fields, data[this.formConf.formModel])
    this.buildRules(data.formConfCopy.fields, data[this.formConf.formRules])
    this.initRuleConfig(data.formConfCopy, data.ruleConfig,data[this.formConf.formModel])
    return data
  },
  methods: {
    testList (newKey) {
       let IndexM;
        this.formConfJson.fields.forEach((item,index)=>{
        if(item.__config__.tag==='Subform' && newKey === item.__config__.renderKey){
          IndexM=index
        }
      })
      return this.formConfJson.fields[IndexM].__config__.children[0].__config__.children
    },
    explicit(renderKey){
      this.$emit('click', renderKey)
    },
    handleSelectionChange(val){
      this.mulArr = [...val]
    },
    //初始化表单规则配置
    initRuleConfig(formConfCopy, ruleConfig,formData) {
      if(formConfCopy.ruleConfig && formConfCopy.ruleConfig.length>0){
        // formConfCopy.ruleConfig.sort((a,b) => {return a.basic.order-b.basic.order}).forEach((cur,index) => {
          let cur = formConfCopy.ruleConfig[0]
          // rule.batch = cur.basic.order
          ruleConfig.hiddenField = cur.hide.join(',')
          ruleConfig.dispalyField = cur.show.join(',')
          ruleConfig.sysFieldRulesListVo = []
          ruleConfig.formList = []
          cur.formrule.forEach((r,ind) => {
            let list = []
            r.rules.forEach((item,index)=>{
              list.push({
                ruleFiledName:item.fieldName,
                ruleValue:item.content,
                sumFiled:item.compare,
                relat:index>0?r.method[index-1]:''
              })
            })
            ruleConfig.sysFieldRulesListVo.push({
              relat:ind>0?cur.method[ind-1]:'',
              sysFieldRuleVo:list
            })
          })
          Object.keys(formData).forEach(key => {
            formData[key] !== null && formData[key] !== undefined && ruleConfig.formList.push({
              filedName: key,
              value: Array.isArray(formData[key])?formData[key].join(','):formData[key]
            })
          })
          // ruleConfig.push(rule)
        // })
        getFormRule(ruleConfig).then((res) => {
          if(res.code === 0) {
            if(res.data !== null && res.data !== '不符合规则'){
              this.hiddenFields = res.data.hiddenField.split(',')
              this.changeShowHide(formConfCopy.fields,this.hiddenFields)
            } else {
              this.hiddenFields = []
              this.changeShowHide(formConfCopy.fields,this.hiddenFields)
            }
          }
        }).catch(e=>console.log(e))
      }
    },
    //根据表单规则更改字段显隐
    changeShowHide(componentList,hidden){
      componentList.forEach((cur,index) => {
        if(hidden.includes(cur.__vModel__)){
          this.$set(cur,'hide',true)
        } else {
          this.$set(cur,'hide',false)
        }
        if (cur.__config__.children) this.changeShowHide(cur.__config__.children,hidden)
      })
    },
    initFormData(componentList, formData) {
      componentList.forEach((cur,index) => {
        const config = cur.__config__
        config.defaultValue = this.originData[cur.__vModel__]?this.originData[cur.__vModel__]:config.defaultValue
        if (cur.__vModel__) formData[cur.__vModel__] = config.defaultValue
        if (config.tag === 'el-upload') {
          cur['file-list'] = config.defaultValue ? config.defaultValue : []
        }
        if (config.children) this.initFormData(config.children, formData)
      })
    },
    buildRules(componentList, rules) {
      componentList.forEach(cur => {
        const config = cur.__config__
        if (Array.isArray(config.regList)) {
          if (config.required) {
            const required = { required: config.required, message: cur.placeholder }
            if (Array.isArray(config.defaultValue)) {
              required.type = 'array'
              required.message = `请至少选择一个${config.label}`
            }
            required.message === undefined && (required.message = `${config.label}不能为空`)
            config.regList.push(required)
          }
          rules[cur.__vModel__] = config.regList.map(item => {
            item.pattern && (item.pattern = eval(item.pattern))
            item.validator && (item.validator = eval(item.validator.replace('\n', '')))
            item.trigger = ruleTrigger && ruleTrigger[config.tag]
            return item
          })
        }
        if (config.children) this.buildRules(config.children, rules)
      })
    },
    //重置
    resetForm() {
      this.formConfCopy = deepClone(this.formConf)
      this.$refs[this.formConf.formRef].resetFields()
      setShowHide.call(this)
      this.$emit('reset')
    },
    //提交
    submitForm() {
      if (window.location.pathname.indexOf('/formdesign') !== -1) {
         return this.$message.warning('预览不支持数据提交')
      }
      this.$refs[this.formConf.formRef].validate(valid => {
        if (!valid) return false
        // 触发 submit 事件
        // update by awesome
        this.$emit('submit', this[this.formConf.formModel])
        // this.$emit('submit', {
        //   conf: this.formConfCopy,
        //   values: this[this.formConf.formModel]
        // })
        return true
      })
    },
    //保存,存到草稿
    saveForm() {
      this.$refs[this.formConf.formRef].validate(valid => {
        if (!valid) return false
        if(this.$store.state.currentStep.step<child.length-1)  this.$store.commit('DOWN')
        this.$emit('save', this[this.formConf.formModel])
        return true
      })
    },
    //取消
    cancelForm() {
      this.$emit('cancel')
    },
    //为el-upload绑定一个on-success、on-remove事件，并将返回值返回给表单
    bindUploadSuccess(fields, target) {
      fields.map((item) => {
        if (item.action) {
          item.action=`${process.env.VUE_APP_BASE_API}/admin-api/form/project/fileUpload`
          item.headers= { Authorization: "Bearer " + getAccessToken() }
          item['on-success'] = (res, file, fileList) => {
             this[target][item.__vModel__] = fileList.map((item)=>{
               return item.response?item.response:item
              })
             item['file-list'] = this[target][item.__vModel__]
          }
          item['on-remove'] = (file, fileList) => {
            this[target][item.__vModel__] = fileList.map((item)=>{
              return item.response?item.response:item
            })
            item['file-list'] = this[target][item.__vModel__]
          }
        }
        if (item.__config__.tag === 'el-tabs' || item.__config__.tag === 'Steps'|| item.__config__.tag === 'el-collapse') {
          item.__config__.children.map((data) => {
            this.bindUploadSuccess(data.__config__.children,target)
          })
        }
      })
    }
  },
  render(h) {
    return renderFrom.call(this, h)
  }
}
</script>
